package com.payvar.flutter_bluetooth_plugin;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.google.gson.Gson;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class FlutterBluetoothPlugin implements MethodChannel.MethodCallHandler, ActivityAware, FlutterPlugin, DeviceCallback {
    public FlutterBluetoothPlugin() {
    }

    private Activity activity;
    private Object initializationLock = new Object();
    private Application application;
    private MethodChannel methodChannel;
    private static final String CHANNEL_NAME = "flutter_bluetooth_plugin";
    private static FlutterBluetoothPlugin instance;
    private MethodCall pendingCall;
    private EventChannel stateChannel;
    private MethodChannel.Result pendingResult;
    private FlutterPlugin.FlutterPluginBinding pluginBinding;
    private ActivityPluginBinding activityBinding;
    private static final Gson sGson = new Gson();

    private Map<String, Integer> stateMap = new HashMap<>();
    private Map<String,String> messageMap = new HashMap<>();
    //服务uuid
    public static UUID UUID_SERVER = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb");
    //读的特征值¸
    public static UUID UUID_CHAR_READ = UUID.fromString("0000ffe3-0000-1000-8000-00805f9b34fb");
    //写的特征值
    public static UUID UUID_CHAR_WRITE = UUID.fromString("0000ffe4-0000-1000-8000-00805f9b34fb");
    private BLEManager mBleManager;


    Map mParammap = new HashMap();
    Map<String,BlueBean> deviceMap=new HashMap<>();


    @Override
    public void deviceResult(BluetoothDevice device, int rssi) {
        //要去重复

        BlueBean blueBean = new BlueBean();

            blueBean.setAddress(TextUtils.isEmpty(device.getAddress()) ? "" : device.getAddress());
            blueBean.setName(TextUtils.isEmpty(device.getName()) ? "" : device.getName());
            blueBean.setRssi(rssi);
            blueBean.setDevice(device);
            deviceMap.put(device.getAddress(),blueBean);

            mParammap.put("data", sGson.toJson(blueBean));
            methodChannel.invokeMethod("deviceResultListener", mParammap);



    }


    ///方法回调

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {

        if (!mBleManager.isSupportBle()) {
            String s = sGson.toJson(new ErrorMessage(-100, "error"));
            result.success(s);

            return;
        }
        switch (call.method) {
            case "isAvailable": //是否可用
                break;
            case "boundDevices":
                break;
            case "turnOn":
                mBleManager.enableBluetooth();
                result.success(sGson.toJson(new ErrorMessage(200, "success")));
                break;
            case "turnOff":
                mBleManager.off();

                result.success(sGson.toJson(new ErrorMessage(200, "success")));
                break;
            case "startScan":
                mBleManager.startScan(this);
                result.success(sGson.toJson(new ErrorMessage(200, "success")));
                break;
            case "stopScan":
                mBleManager.stopScan();
                result.success(sGson.toJson(new ErrorMessage(200, "success")));
                break;
            case "connectDevice":
                if (call.hasArgument("connectDeviceAddress")) {
                    String address = call.argument("connectDeviceAddress");
                    BlueBean blueBe = deviceMap.get(address);
                    mBluetoothGatt = blueBe.getDevice().connectGatt(activity, false, bluetoothGattCallback);

                }
                break;
            case "disConnectDevice":
                break;
            case "sendMsg":
                if (call.hasArgument("msg")) {
                    String msg = call.argument("msg");
                    if (mBluetoothGatt == null) {
                        return;
                    }
                    //找到服务
                    BluetoothGattService service = mBluetoothGatt.getService(UUID_SERVER);
                    if (service == null) {
                        return;
                    }
                    //拿到写的特征值
                    BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_CHAR_WRITE);
                    mBluetoothGatt.setCharacteristicNotification(characteristic, true);


                    try {
                        new SplitWriterClient().splitWrite(characteristic, mBluetoothGatt, msg.getBytes("GBK"));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    BleLog.d("sendData 发送数据成功");

                }
                break;
        }

    }

    private BluetoothGatt mBluetoothGatt;
    private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                //查找服务
                stateMap.put("state",0);
                invokeMethod("blueState",stateMap);
                gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_CONNECTING) {
                BleLog.d("onConnectionStateChange 连接中......");
                stateMap.put("state",1);
                invokeMethod("blueState",stateMap);
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                BleLog.d( "onConnectionStateChange 连接断开");
                stateMap.put("state",2);
                invokeMethod("blueState",stateMap);
            } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                BleLog.d( "onConnectionStateChange 连接断开中......");
                stateMap.put("state",3);
                invokeMethod("blueState",stateMap);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            //设置读特征值的监听，接收服务端发送的数据
            BluetoothGattService service = gatt.getService(UUID_SERVER);
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_CHAR_READ);
            boolean b = gatt.setCharacteristicNotification(characteristic, true);
            BleLog.d("onServicesDiscovered 设置通知 " + b);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);

            try {
                String gbkChinese = new String(characteristic.getValue(),"GBK");
                messageMap.put("message",gbkChinese);
                invokeMethod("messageListener",messageMap);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            // String unicodeChinese = new String(gbkChinese.getBytes("ISO-8859-1"),"GBK");



        }
    };


    StringBuffer stringBuffer=new StringBuffer();
    /**
     * Plugin registration.
     */
    public static void registerWith(PluginRegistry.Registrar registrar) {
        if (instance == null) {
            instance = new FlutterBluetoothPlugin();
        }
        Activity activity = registrar.activity();
        Application application = null;
        if (registrar.context() != null) {
            application = (Application) (registrar.context().getApplicationContext());
        }

        instance.init(registrar.messenger(), application, activity, registrar, null);
    }

    private void init(
            final BinaryMessenger messenger,
            final Application application,
            final Activity activity,
            final PluginRegistry.Registrar registrar,
            final ActivityPluginBinding activityBinding) {
        synchronized (initializationLock) {
            this.activity = activity;
            this.application = application;
            methodChannel = new MethodChannel(messenger, CHANNEL_NAME);
            methodChannel.setMethodCallHandler(this);
            // 得到本地蓝牙适配器
            mBleManager = BLEManager.getInstance(application);
            stateChannel = new EventChannel(messenger, CHANNEL_NAME + "/state");
        }
    }





    private void invokeMethod(final String name, final Object obj) {
        activity.runOnUiThread(() -> {
            methodChannel.invokeMethod(name, obj);
        });
    }


    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
        pluginBinding = binding;

    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        pluginBinding = null;
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {
        onDetachedFromActivity();
    }

    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
        onAttachedToActivity(binding);
    }

    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        activityBinding = binding;
        init(
                pluginBinding.getBinaryMessenger(),
                (Application) pluginBinding.getApplicationContext(),
                activityBinding.getActivity(),
                null,
                activityBinding);
    }


    @Override
    public void onDetachedFromActivity() {
        release();
    }

    private void release() {
        activityBinding = null;
        methodChannel.setMethodCallHandler(null);
        methodChannel = null;
        stateChannel.setStreamHandler(null);
        stateChannel = null;
        application = null;



    }


}
